home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / getclass.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  45KB  |  1,118 lines

  1. // $Id: getclass.cpp,v 1.7 1999/03/09 14:37:17 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <sys/stat.h>
  12. #include "control.h"
  13. #include "semantic.h"
  14. #include "access.h"
  15. #include "getclass.h"
  16. #include "zip.h"
  17.  
  18. inline u1 Semantic::GetU1(char *buffer)
  19. {
  20.     return *buffer;
  21. }
  22.  
  23. inline u2 Semantic::GetU2(char *buffer)
  24. {
  25.     u2 i = (u1) *buffer++;
  26.     return (i << 8) + (u1) *buffer;
  27. }
  28.  
  29. inline u4 Semantic::GetU4(char *buffer)
  30. {
  31.     u4 i = (u1) *buffer++;
  32.     i = (i << 8) + (u1) *buffer++;
  33.     i = (i << 8) + (u1) *buffer++;
  34.     return (i << 8) + (u1) *buffer;
  35. }
  36.  
  37. inline u1 Semantic::GetAndSkipU1(char *&buffer)
  38. {
  39.     return (u1) *buffer++;
  40. }
  41.  
  42. inline u2 Semantic::GetAndSkipU2(char *&buffer)
  43. {
  44.     u2 i = (u1) *buffer++;
  45.     return (i << 8) + (u1) *buffer++;
  46. }
  47.  
  48. inline u4 Semantic::GetAndSkipU4(char *&buffer)
  49. {
  50.     u4 i = (u1) *buffer++;
  51.     i = (i << 8) + (u1) *buffer++;
  52.     i = (i << 8) + (u1) *buffer++;
  53.     return (i << 8) + (u1) *buffer++;
  54. }
  55.  
  56. inline void Semantic::Skip(char *&buffer, int n)
  57. {
  58.     buffer += n;
  59. }
  60.  
  61.  
  62. TypeSymbol *Semantic::ProcessNestedType(TypeSymbol *base_type, NameSymbol *name_symbol, LexStream::TokenIndex tok)
  63. {
  64.     TypeSymbol *inner_type = base_type -> FindTypeSymbol(name_symbol);
  65.     if (! inner_type)
  66.     {
  67.         int length = base_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $
  68.         wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
  69.         wcscpy(external_name, base_type -> ExternalName());
  70.         wcscat(external_name, StringConstant::US__DS_);
  71.         wcscat(external_name, name_symbol -> Name());
  72.         NameSymbol *external_name_symbol = control.FindOrInsertName(external_name, length);
  73.  
  74.         delete [] external_name;
  75.  
  76.         inner_type = base_type -> InsertNestedTypeSymbol(name_symbol);
  77.         inner_type -> outermost_type = base_type -> outermost_type;
  78.         inner_type -> supertypes_closure = new SymbolSet;
  79.         inner_type -> subtypes = new SymbolSet;
  80.         inner_type -> SetExternalIdentity(external_name_symbol);
  81.         inner_type -> SetOwner(base_type);
  82.         inner_type -> SetSignature(control);
  83.  
  84.         FileSymbol *file_symbol = Control::GetFile(base_type -> ContainingPackage(), external_name_symbol, control.option.depend);
  85.         if (file_symbol)
  86.         {
  87.             inner_type -> file_symbol = file_symbol;
  88.             inner_type -> SetLocation();
  89.  
  90.             ReadClassFile(inner_type, tok);
  91.         }
  92.         else
  93.         {
  94.             inner_type -> SetSymbolTable(1); // this symbol table will only contain a default constructor
  95.             inner_type -> super = control.Object();
  96.             inner_type -> MarkBad();
  97.             AddDefaultConstructor(inner_type);
  98.             ReportSemError(SemanticError::TYPE_NOT_FOUND,
  99.                            tok,
  100.                            tok,
  101.                            inner_type -> ContainingPackage() -> PackageName(),
  102.                            inner_type -> ExternalName());
  103.         }
  104.     }
  105.  
  106.     return inner_type;
  107. }
  108.  
  109.  
  110. TypeSymbol *Semantic::RetrieveNestedTypes(TypeSymbol *base_type, wchar_t *signature, LexStream::TokenIndex tok)
  111. {
  112.     int len;
  113.     for (len = 0; signature[len] != U_NULL && signature[len] != U_DOLLAR; len++)
  114.         ;
  115.     NameSymbol *name_symbol = control.FindOrInsertName(signature, len);
  116.     TypeSymbol *inner_type = ProcessNestedType(base_type, name_symbol, tok);
  117.  
  118.     return (signature[len] == U_DOLLAR ? RetrieveNestedTypes(inner_type, &signature[len + 1], tok) : inner_type);
  119. }
  120.  
  121.  
  122. TypeSymbol *Semantic::ReadType(TypeSymbol *base_type, wchar_t *signature, LexStream::TokenIndex tok)
  123. {
  124.     int total_length;
  125.  
  126.     for (total_length = 0; signature[total_length] != U_NULL && signature[total_length] != U_DOLLAR; total_length++)
  127.         ;
  128.     if (signature[total_length] != U_NULL && Code::IsDigit(signature[total_length + 1])) // an anonymous or a local type?
  129.     {
  130.         for (total_length += 2; Code::IsDigit(signature[total_length]); total_length++) // will stop at next '$' or '\0' !!!
  131.             ;
  132.         if (signature[total_length] != U_NULL) // not an anonymous type ?  then, it's a local type: scan local name
  133.         {
  134.             for (total_length++; signature[total_length] != U_NULL && signature[total_length] != U_DOLLAR; total_length++)
  135.                 ;
  136.         }
  137.     }
  138.  
  139.     int len;
  140.     for (len = total_length - 1; len >= 0 && signature[len] != U_SLASH; len--)
  141.         ;
  142.  
  143.     wchar_t *name = &(signature[len + 1]);
  144.  
  145.     //
  146.     // When a package name is specified in the signature, we look for the type in question
  147.     // in that package, i.e., we redefine package. Otherwise, we search for the type in the
  148.     // unnamed package.
  149.     //
  150.     PackageSymbol *package = NULL;
  151.  
  152.     //
  153.     // Which package?
  154.     //
  155.     if (len >= 0)
  156.     {
  157.         wchar_t *package_name = new wchar_t[len + 1];
  158.         for (int i = 0; i < len; i++)
  159.             package_name[i] = signature[i];
  160.         package_name[len] = U_NULL;
  161.         package = control.ProcessPackage(package_name);
  162.  
  163.         if (package -> directory.Length() == 0)
  164.         {
  165.             ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
  166.                            tok,
  167.                            tok,
  168.                            package -> PackageName());
  169.         }
  170.         delete [] package_name;
  171.     }
  172.     else package = control.unnamed_package;
  173.  
  174.     //
  175.     // Process type
  176.     //
  177.     NameSymbol *name_symbol = control.FindOrInsertName(name, total_length - (len + 1));
  178.     TypeSymbol *type = package -> FindTypeSymbol(name_symbol);
  179.     if (type)
  180.     {
  181.         if (type -> SourcePending())
  182.             control.ProcessHeaders(type -> file_symbol);
  183.     }
  184.     else
  185.     {
  186.         FileSymbol *file_symbol = Control::GetFile(package, name_symbol, control.option.depend);
  187.  
  188.         //
  189.         // If we are dealing with the unnamed package, ...
  190.         //
  191.         if ((! file_symbol) && package == control.unnamed_package)
  192.             file_symbol = Control::GetFile(control.unnamed_package, name_symbol, control.option.depend);
  193.  
  194.         //
  195.         // If a file_symbol was not found, ReadType will issue an error message
  196.         //
  197.         type = ReadType(file_symbol, package, name_symbol, tok);
  198.  
  199.         //
  200.         // If we have to do a full check and we have a case where a ".class" file
  201.         // depends on a ".java" file then we should signal that the ".java" file
  202.         // associated with the ".class" file should be recompiled.
  203.         //
  204.         if (control.option.full_check && (! control.option.depend) &&
  205.             file_symbol && file_symbol -> IsJava() && (! file_symbol -> IsZip()))
  206.         {
  207.             control.recompilation_file_set.AddElement(file_symbol);
  208.             if (! control.option.incremental && control.option.pedantic)
  209.             {
  210.                 ReportSemError(SemanticError::RECOMPILATION,
  211.                                tok,
  212.                                tok,
  213.                                base_type -> ContainingPackage() -> Name(), 
  214.                                base_type -> ExternalName(), 
  215.                                type -> ContainingPackage() -> Name(), 
  216.                                type -> ExternalName());
  217.             }
  218.         }
  219.     }
  220.  
  221.     //
  222.     // Establish a dependence from base_type (read from a class file) to type.
  223.     //
  224.     AddDependence(base_type, type, tok);
  225.  
  226.     return (signature[total_length] == U_DOLLAR ? RetrieveNestedTypes(type, &signature[total_length + 1], tok) : type);
  227. }
  228.  
  229.  
  230. TypeSymbol *Semantic::ProcessSignature(TypeSymbol *base_type, char *signature, LexStream::TokenIndex tok)
  231. {
  232.     TypeSymbol *type;
  233.     int num_dimensions = 0;
  234.  
  235.     for (; *signature == U_LEFT_BRACKET; signature++)
  236.         num_dimensions++;
  237.  
  238.     switch(*signature)
  239.     {
  240.         case U_B:
  241.              type = control.byte_type;
  242.              break;
  243.         case U_C:
  244.              type = control.char_type;
  245.              break;
  246.         case U_D:
  247.